﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Fadada.FASC.SDK.DotNetCore.Attributes;
using Fadada.FASC.SDK.DotNetCore.Interfaces;
using Fadada.FASC.SDK.DotNetCore.Model;
using Fadada.FASC.SDK.DotNetCore.Utils;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace Fadada.FASC.SDK.DotNetCore.Services
{
    public class GetUploadFileService<T1, T2> : IGetUploadFileService<T1, T2>
    where T1 : class
    where T2 : class
    {
        public async Task<ResponseBodyInfo<T1>> UploadFileAsync(T2 inputBody, BaseInputInfo inputInfo, FileItem fileItem, string token)
        {
            var attributeInfo = GetUrlAttribute(inputBody);
            inputInfo.ReqEndPoint = attributeInfo.Url;
            inputInfo.ReqMethod = attributeInfo.Method;
            var reqStr = JsonConvert.SerializeObject(inputBody, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
            var body = new Dictionary<string, string>() { { "bizContent", reqStr } };
            string strTimeStamp = ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000).ToString();//毫秒值
            string strGUID = Guid.NewGuid().ToString("N");
            Dictionary<string, string> headerParames = new Dictionary<string, string>();//参数摘要计算得map
            headerParames.Add("X-FASC-App-Id", inputInfo.APP_ID);
            headerParames.Add("X-FASC-Sign-Type", "HMAC-SHA256");
            headerParames.Add("X-FASC-Timestamp", strTimeStamp);
            headerParames.Add("X-FASC-Nonce", strGUID);
            headerParames.Add("X-FASC-AccessToken", token);
            headerParames.Add("bizContent", EncodeNonAsciiCharacters(body["bizContent"]));
            string strSign = SignUtil.GetSign(headerParames, strTimeStamp, inputInfo.APP_SECRET);

            headerParames.Add("X-FASC-Sign", strSign);
            var client = HttpWebHelp.CreateDefault(inputInfo.ReqDomainName + inputInfo.ReqEndPoint);
            foreach (var p in headerParames)
            {
                client.Headers[p.Key] = p.Value;
            }
            IDictionary<string, FileItem> files = new Dictionary<string, FileItem>();
            files["fileContent"] = fileItem;
            client.Method = inputInfo.ReqMethod;
            client.ContentType = "multipart/form-data";
            client.SubmitFormData(body, files);
            var rspResponse = await Task.Run(() => client.GetResponseIgnoreServerError());
            var rspStr = rspResponse.GetResponseString();
            return JsonConvert.DeserializeObject<ResponseBodyInfo<T1>>(rspStr);
        }

        public static string EncodeNonAsciiCharacters(string value)
        {
            StringBuilder sb = new StringBuilder();
            foreach (char c in value)
            {
                if (c > 127)
                {
                    // This character is too big for ASCII
                    string encodedValue = "\\u" + ((int)c).ToString("x4");
                    sb.Append(encodedValue);
                }
                else
                {
                    sb.Append(c);
                }
            }
            return sb.ToString();
        }

        private RemoteServiceAttribute GetUrlAttribute(T2 req)
        {
            var urlAttribute = req.GetType().GetCustomAttributes(false).First(r => r is RemoteServiceAttribute) as RemoteServiceAttribute;
            return urlAttribute;
        }
    }
}